// 字典序最小的拓扑排序
// 要求返回所有正确的拓扑排序中 字典序最小 的结果
// 建图请使用链式前向星方式，因为比赛平台用其他建图方式会卡空间
// 测试链接 : https://www.luogu.com.cn/problem/U107394
// 提交命名空间 Code1 或 Code2 中的所有代码，可以直接通过

// Code1 使用的是自己实现的堆
namespace Code1
{
    #include <iostream>
    #include <algorithm>

    using namespace std;

    const int MAXN = 100001; // 点的最大数量
    const int MAXM = 100001; // 边的最大数量
    int n, m; // 题目的输入参数

    // 链式前向星建图 
    int head[MAXN];
    int next[MAXM];
    int to[MAXM];
    int cnt = 1; // 边号

    int indegree[MAXN]; // 拓扑排序用到的入度表
    int ret[MAXN]; // 收集拓扑排序的结果
    // 拓扑排序，不用队列，用小根堆，为了得到字典序最小的拓扑排序
    int heap[MAXN];
    int heapSize; // 堆中的元素个数

    // 清理之前的脏数据
    void build(int n)
    {
        cnt = 1;
        heapSize = 0;
        fill(head, head + n + 1, 0);
        fill(indegree, indegree + n + 1, 0);
    }

    // 用链式前向星建图
    void addEdge(int u, int v)
    {
        ::next[cnt] = head[u];
        to[cnt] = v;
        head[u] = cnt++;
    }

    // 交换堆上两个位置的数字
    void swap(int i, int j)
    {
        std::swap(heap[i], heap[j]);
    }

    // 小根堆里加入数字（向上调整算法）
    void push(int num)
    {
        int i = heapSize++;
        heap[i] = num;
        // heapInsert 的过程
        while(heap[i] < heap[(i - 1) / 2])
        {
            ::swap(i, (i - 1) / 2); // 加上全局作用域 ::，避免函数调用的二义性
            i = (i - 1) / 2;
        }
    }

    // 小根堆里弹出最小值（向下调整算法）
    int pop()
    {
        int ans = heap[0];
        heap[0] = heap[--heapSize];
        // heapify 的过程
        int i = 0, l = 2 * i + 1;
        while(l < heapSize)
        {
            // 选择较小的孩子和父亲 PK
            int best = l + 1 < heapSize && heap[l + 1] < heap[l] ? l + 1 : l;
            best = heap[best] < heap[i] ? best : i;
            if(best == i) break; // 没有孩子比父亲小，没有 PK 过父亲
            ::swap(best, i); // 交换孩子和父亲的位置
            i = best; // 父亲来到孩子的位置
            l = 2 * i + 1; // 和下一个孩子 PK
        }
        return ans;
    }

    // 判断小根堆是否为空
    bool isEmpty()
    {
        return heapSize == 0;
    }

    void topoSort()
    {
        for(int i = 1; i <= n; ++i)
        {
            if(indegree[i] == 0) push(i);
        }
        
        int fill = 0; 
        while(!isEmpty())
        {
            int x = pop();
            ret[fill++] = x;
            // 用链式前向星的方式，遍历 x 的相邻节点
            for(int ei = head[x]; ei != 0; ei = ::next[ei])
            {
                if(--indegree[to[ei]] == 0)
                {
                    push(to[ei]);
                }
            }
        }
    }

    int main()
    {
        cin >> n >> m;
        for(int i = 0; i < m; ++i)
        {
            int from, to;
            cin >> from >> to;
            addEdge(from, to);
            ++indegree[to];
        }
        
        topoSort();
        for(int i = 0; i < n - 1; ++i)
        {
            cout << ret[i] << " ";
        }
        cout << ret[n - 1] << endl;
        
        return 0;
    }
}


// Code2 使用的是标准库提供的堆
namespace Code2
{
    #include <iostream>
    #include <vector>
    #include <queue>

    using namespace std;

    int MAXN = 100001; // 点的最大数量
    int MAXM = 100001; // 边的最大数量
    int n, m;
    int cnt = 1;
    vector<int> head(MAXN);
    vector<int> next(MAXM);
    vector<int> to(MAXM);
    vector<int> indegree(MAXN);
    vector<int> ret;

    void addEdge(int u, int v)
    {
        ::next[cnt] = head[u];
        to[cnt] = v;
        head[u] = cnt++;
    }

    void topoSort()
    {
        priority_queue<int, vector<int>, greater<int>> q;
        for(int i = 1; i <= n; ++i)
        {
            if(!indegree[i]) q.push(i);
        }
        
        while(!q.empty())
        {
            int x = q.top();
            q.pop();
            ret.push_back(x);
            for(int ei = head[x]; ei; ei = ::next[ei])
            {
                if(--indegree[to[ei]] == 0)
                {
                    q.push(to[ei]);
                }
            }
        }
    }

    int main()
    {
        cin >> n >> m;
        for(int i = 0; i < m; ++i)
        {
            int from, to;
            cin >> from >> to;
            addEdge(from, to);
            ++indegree[to];
        }
        
        topoSort();
        for(int i = 0; i < n - 1; ++i)
        {
            cout << ret[i] << " ";
        }
        cout << ret[n - 1] << endl;
        
        return 0;
    }
}